package com.yanqu.road.dao.impl.kowloon.config;

import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.impl.TempDao;
import com.yanqu.road.entity.config.system.NormalWeightItem;
import com.yanqu.road.entity.kowloon.common.KowloonBuffParam;
import com.yanqu.road.entity.kowloon.common.KowloonRange;
import com.yanqu.road.entity.kowloon.config.KowloonBuildingConfig;
import com.yanqu.road.entity.kowloon.config.KowloonNpcAttributeConfig;
import com.yanqu.road.entity.kowloon.config.KowloonNpcConfig;
import com.yanqu.road.entity.kowloon.config.KowloonMissionRoadConfig;
import com.yanqu.road.entity.kowloon.enums.eKowloonNpcType;
import com.yanqu.road.utils.string.StringUtils;

import java.lang.reflect.Field;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class KowloonConfigDaoImpl extends TempDao {
    private static String getKowloonBuildingConfigSql = "select * from `t_p_kowloon_building` ";

    public Map<Integer, Map<Integer, KowloonBuildingConfig>> getKowloonBuildingConfigMap() {
        Map<Integer, Map<Integer, KowloonBuildingConfig>> map = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DbNameStrategy.getConfigDb());
            call = getDb().getConnection().prepareCall(getKowloonBuildingConfigSql);
            rs = call.executeQuery();
            while (rs.next()) {
                KowloonBuildingConfig kowloonBuildingConfig = new KowloonBuildingConfig();
                kowloonBuildingConfig.setId(rs.getInt("id"));
                kowloonBuildingConfig.setBuildId(rs.getInt("buildId"));
                kowloonBuildingConfig.setLevel(rs.getInt("level"));
                String skillsList = rs.getString("skillsList");
                if (!StringUtils.isNullOrEmpty(skillsList)) {
                    kowloonBuildingConfig.setSkillsList(StringUtils.stringToStringList(skillsList, "\\|"));
                }
                kowloonBuildingConfig.setNeedPassId(rs.getInt("needPassId"));
                kowloonBuildingConfig.setUnlockCost(rs.getString("unlockCost"));
                kowloonBuildingConfig.setProsperousValue(rs.getLong("prosperousValue"));
                Map<Integer, KowloonBuildingConfig> levelMap = map.getOrDefault(kowloonBuildingConfig.getBuildId(), new ConcurrentHashMap<>());
                levelMap.put(kowloonBuildingConfig.getLevel(), kowloonBuildingConfig);
                map.put(kowloonBuildingConfig.getBuildId(), levelMap);
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return map;
    }


    private static String getKowloonMissionRoadConfigSql = "select * from `t_p_kowloon_mission_road` ";

    public Map<Integer, Map<Integer, KowloonMissionRoadConfig>> getKowloonMissionRoadConfigMap() {
        Map<Integer, Map<Integer, KowloonMissionRoadConfig>> map = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DbNameStrategy.getConfigDb());
            call = getDb().getConnection().prepareCall(getKowloonMissionRoadConfigSql);
            rs = call.executeQuery();
            while (rs.next()) {
                KowloonMissionRoadConfig kowloonMissionRoadConfig = new KowloonMissionRoadConfig();
                kowloonMissionRoadConfig.setId(rs.getInt("id"));
                kowloonMissionRoadConfig.setMissionRoadId(rs.getInt("missionRoadId"));
                kowloonMissionRoadConfig.setIncome(rs.getString("income"));
                kowloonMissionRoadConfig.setMaxTime(rs.getInt("maxTime"));
                kowloonMissionRoadConfig.setWave(rs.getInt("wave"));
                kowloonMissionRoadConfig.setStepNum(rs.getInt("StepNum"));
                kowloonMissionRoadConfig.setNeedPower(rs.getLong("needPower"));
                String juniorSkillsList = rs.getString("juniorSkillsList");
                if (!StringUtils.isNullOrEmpty(juniorSkillsList)) {
                    kowloonMissionRoadConfig.setJuniorSkillsList(NormalWeightItem.parseWeightItemList(juniorSkillsList));
                }
                String middleSkillsList = rs.getString("middleSkillsList");
                if (!StringUtils.isNullOrEmpty(middleSkillsList)) {
                    kowloonMissionRoadConfig.setMiddleSkillsList(NormalWeightItem.parseWeightItemList(middleSkillsList));
                }
                String highSkillsList = rs.getString("highSkillsList");
                if (!StringUtils.isNullOrEmpty(highSkillsList)) {
                    kowloonMissionRoadConfig.setHighSkillsList(NormalWeightItem.parseWeightItemList(highSkillsList));
                }
                String elementWeights = rs.getString("elementWeights");
                if (!StringUtils.isNullOrEmpty(elementWeights)) {
                    List<Integer> list = StringUtils.stringToIntegerList(elementWeights, "\\|");
                    while (list.size() < 4) {
                        list.add(0);
                    }
                    kowloonMissionRoadConfig.setElementWeights(list);
                }
                kowloonMissionRoadConfig.setSilverIngotWeights(rs.getInt("silverIngotWeights"));
                String ruffianIdList = rs.getString("ruffianIdList");
                if (!StringUtils.isNullOrEmpty(ruffianIdList)) {
                    kowloonMissionRoadConfig.setRuffianIdList(StringUtils.stringToIntegerList(ruffianIdList, "\\|"));
                }
                String ruffianNum = rs.getString("ruffianNum");
                if (!StringUtils.isNullOrEmpty(ruffianNum)) {
                    kowloonMissionRoadConfig.setRuffianNum(StringUtils.stringToIntegerList(ruffianNum, "\\|"));
                }
                String ruffianHp = rs.getString("ruffianHp");
                if (!StringUtils.isNullOrEmpty(ruffianHp)) {
                    kowloonMissionRoadConfig.setRuffianHp(StringUtils.stringToLongList(ruffianHp, "\\|"));
                }
                String ruffianWalkRoute = rs.getString("ruffianWalkRoute");
                if (!StringUtils.isNullOrEmpty(ruffianWalkRoute)) {
                    kowloonMissionRoadConfig.setRuffianWalkRoute(StringUtils.stringToStringList(ruffianWalkRoute, "\\|"));
                }
                String ruffianDelayTime = rs.getString("ruffianDelayTime");
                if (!StringUtils.isNullOrEmpty(ruffianDelayTime)) {
                    kowloonMissionRoadConfig.setRuffianDelayTime(StringUtils.stringToIntegerList(ruffianDelayTime, "\\|"));
                }
                String resourceSizeRandom = rs.getString("resourceSizeRandom");
                if (!StringUtils.isNullOrEmpty(resourceSizeRandom)) {
                    kowloonMissionRoadConfig.setResourceSizeRandom(StringUtils.stringToStringList(resourceSizeRandom, "\\|"));
                }
                String moveRandom = rs.getString("moveRandom");
                if (!StringUtils.isNullOrEmpty(moveRandom)) {
                    kowloonMissionRoadConfig.setMoveRandom(StringUtils.stringToStringList(moveRandom, "\\|"));
                }
                String weightAddList = rs.getString("weightAddList");
                if (!StringUtils.isNullOrEmpty(weightAddList)) {
                    kowloonMissionRoadConfig.setWeightAddList(StringUtils.stringToIntegerList(weightAddList, ";"));
                }
                kowloonMissionRoadConfig.setOnceReward(rs.getString("onceReward"));
                Map<Integer, KowloonMissionRoadConfig> waveMap = map.getOrDefault(kowloonMissionRoadConfig.getMissionRoadId(), new ConcurrentHashMap<>());
                waveMap.put(kowloonMissionRoadConfig.getWave(), kowloonMissionRoadConfig);
                map.put(kowloonMissionRoadConfig.getMissionRoadId(), waveMap);
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return map;
    }


    private static String getKowloonHeroConfigSql = "select * from `t_p_kowloon_npc` ";

    public Map<eKowloonNpcType, Map<Integer, Map<Integer, Map<Integer, KowloonNpcConfig>>>> getKowloonNpcConfigMap() {
        Map<eKowloonNpcType, Map<Integer, Map<Integer, Map<Integer, KowloonNpcConfig>>>> map = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DbNameStrategy.getConfigDb());
            call = getDb().getConnection().prepareCall(getKowloonHeroConfigSql);
            rs = call.executeQuery();
            while (rs.next()) {
                KowloonNpcConfig kowloonNpcConfig = new KowloonNpcConfig();
                kowloonNpcConfig.setId(rs.getInt("id"));
                kowloonNpcConfig.setNpcId(rs.getInt("npcId"));
                kowloonNpcConfig.setType(rs.getInt("type"));
                kowloonNpcConfig.setLevel(rs.getInt("level"));
                kowloonNpcConfig.setMergeLevel(rs.getInt("mergeLevel"));
                kowloonNpcConfig.setUpCost(rs.getString("upCost"));
                kowloonNpcConfig.setUnlockCond(rs.getString("unlockCond"));
                kowloonNpcConfig.setPower(rs.getLong("power"));
                String juniorSkillsList = rs.getString("juniorSkillsList");
                if (!StringUtils.isNullOrEmpty(juniorSkillsList)) {
                    kowloonNpcConfig.setJuniorSkillsList(NormalWeightItem.parseWeightItemList(juniorSkillsList));
                }
                String middleSkillsList = rs.getString("middleSkillsList");
                if (!StringUtils.isNullOrEmpty(middleSkillsList)) {
                    kowloonNpcConfig.setMiddleSkillsList(NormalWeightItem.parseWeightItemList(middleSkillsList));
                }
                String highSkillsList = rs.getString("highSkillsList");
                if (!StringUtils.isNullOrEmpty(highSkillsList)) {
                    kowloonNpcConfig.setHighSkillsList(NormalWeightItem.parseWeightItemList(highSkillsList));
                }
                // npc属性
                KowloonNpcAttributeConfig npcAttribute = parseNpcAttribute(kowloonNpcConfig.getId(), rs.getString("attributes"));
                kowloonNpcConfig.setNpcAttribute(npcAttribute);
                eKowloonNpcType npcType = eKowloonNpcType.forValue(kowloonNpcConfig.getType());
                if (npcType == null) {
                    throw new RuntimeException("未知npc配置类型,请检查代码" + kowloonNpcConfig.getType());
                }
                Map<Integer, Map<Integer, Map<Integer, KowloonNpcConfig>>> typeMap = map.getOrDefault(npcType, new ConcurrentHashMap<>());
                Map<Integer, Map<Integer, KowloonNpcConfig>> npcLevelMap = typeMap.getOrDefault(kowloonNpcConfig.getNpcId(), new ConcurrentHashMap<>());
                Map<Integer, KowloonNpcConfig> mergeLevelMap = npcLevelMap.getOrDefault(kowloonNpcConfig.getLevel(), new ConcurrentHashMap<>());
                mergeLevelMap.put(kowloonNpcConfig.getMergeLevel(), kowloonNpcConfig);
                npcLevelMap.put(kowloonNpcConfig.getLevel(), mergeLevelMap);
                typeMap.put(kowloonNpcConfig.getNpcId(), npcLevelMap);
                map.put(npcType, typeMap);
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return map;
    }

    private KowloonNpcAttributeConfig parseNpcAttribute(int npcId, String attributes) {
        if (StringUtils.isNullOrEmpty(attributes)) {
            throw new RuntimeException("npcId:" + npcId + "属性配置为空,请检查配置");
        }
        List<String> attributeParamList = StringUtils.stringToStringList(attributes, "\\|");
        Class<KowloonNpcAttributeConfig> aClass = KowloonNpcAttributeConfig.class;
        Field[] fields = aClass.getFields();
        if (attributeParamList.size() < fields.length) {
            throw new RuntimeException("npcId:" + npcId + "属性配置缺少,请检查配置");
        }
        KowloonNpcAttributeConfig npcAttribute = new KowloonNpcAttributeConfig();
        // 攻击力
        npcAttribute.setAtk(Long.parseLong(attributeParamList.get(0)));
        // 攻击频率/每秒攻击xx次×1000
        npcAttribute.setAtkSpeed(Integer.parseInt(attributeParamList.get(1)));
        // 攻击范围/格子
        if (!"0".equals(attributeParamList.get(2))) {
            List<Integer> attackRangeList = StringUtils.stringToIntegerList(attributeParamList.get(2), ";");
            KowloonRange attackRange = new KowloonRange();
            attackRange.setWidth(attackRangeList.get(0));
            attackRange.setHeight(attackRangeList.get(1));
            npcAttribute.setAttackRange(attackRange);
        }
        // 受击范围/格子
        if (!"0".equals(attributeParamList.get(3))) {
            List<Integer> hitRangeList = StringUtils.stringToIntegerList(attributeParamList.get(3), ";");
            KowloonRange hitRange = new KowloonRange();
            hitRange.setWidth(hitRangeList.get(0));
            hitRange.setHeight(hitRangeList.get(1));
            npcAttribute.setHitRange(hitRange);
        }
        // 移动速度/每秒移动xx格子
        npcAttribute.setMoveSpeed(Integer.parseInt((attributeParamList.get(4))));
        // 子弹数量（通用配置）
        npcAttribute.setBullet(Integer.parseInt(attributeParamList.get(5)));
        // 穿透数（攻击敌人数量）
        npcAttribute.setAttackNum(Integer.parseInt(attributeParamList.get(6)));
        // 减速（减速千分比；持续时间/ms；buff叠加次数上限）
        if (!"0".equals(attributeParamList.get(7))) {
            List<Integer> buffParamList = StringUtils.stringToIntegerList(attributeParamList.get(7), ";");
            KowloonBuffParam buffParam = new KowloonBuffParam();
            buffParam.setProbability(buffParamList.get(0));
            buffParam.setDuration(buffParamList.get(1));
            buffParam.setBuffMaxCount(buffParamList.get(2));
            npcAttribute.setSlowParam(buffParam);
        }
        // 冰冻（冰冻概率千分比；持续时间/ms；buff叠加次数上限）
        if (!"0".equals(attributeParamList.get(8))) {
            List<Integer> buffParamList = StringUtils.stringToIntegerList(attributeParamList.get(8), ";");
            KowloonBuffParam buffParam = new KowloonBuffParam();
            buffParam.setProbability(buffParamList.get(0));
            buffParam.setDuration(buffParamList.get(1));
            buffParam.setBuffMaxCount(buffParamList.get(2));
            npcAttribute.setFreezeParam(buffParam);
        }
        // 掉血（伤害为管家婆攻击力的千分比；持续时间/ms；buff叠加次数上限））
        if (!"0".equals(attributeParamList.get(9))) {
            List<Integer> buffParamList = StringUtils.stringToIntegerList(attributeParamList.get(9), ";");
            KowloonBuffParam buffParam = new KowloonBuffParam();
            buffParam.setProbability(buffParamList.get(0));
            buffParam.setDuration(buffParamList.get(1));
            buffParam.setBuffMaxCount(buffParamList.get(2));
            buffParam.getParam().add(buffParamList.get(3));
            npcAttribute.setBleedingParam(buffParam);
        }
        // 眩晕（眩晕概率千分比；持续时间/ms；buff叠加次数上限）
        if (!"0".equals(attributeParamList.get(10))) {
            List<Integer> buffParamList = StringUtils.stringToIntegerList(attributeParamList.get(10), ";");
            KowloonBuffParam buffParam = new KowloonBuffParam();
            buffParam.setProbability(buffParamList.get(0));
            buffParam.setDuration(buffParamList.get(1));
            buffParam.setBuffMaxCount(buffParamList.get(2));
            npcAttribute.setVertigoParam(buffParam);
        }
        // 子弹弹射范围（以地痞为中心N格）
        npcAttribute.setEjectionRange(Integer.parseInt(attributeParamList.get(11)));
        // 武器半径（以好汉为中心）
        npcAttribute.setWeaponRadius(Integer.parseInt(attributeParamList.get(12)));
        // 怪物死后爆炸参数
        if (!"0".equals(attributeParamList.get(13))) {
            npcAttribute.setDeadParamList(StringUtils.stringToIntegerList(attributeParamList.get(13), ";"));
        }
        // 闪现Y轴
        if (!"0".equals(attributeParamList.get(14))) {
            npcAttribute.setFlashYPos(StringUtils.stringToIntegerList(attributeParamList.get(14), ";"));
        }
        // buffCd
        if (!"0".equals(attributeParamList.get(15))) {
            npcAttribute.setBuffCd(StringUtils.stringToIntegerList(attributeParamList.get(15), ";"));
        }

        // 落雷buff 伤害效果
        if (!"0".equals(attributeParamList.get(16))) {
            KowloonBuffParam buffParam = new KowloonBuffParam();
            List<Integer> buffParamList = StringUtils.stringToIntegerList(attributeParamList.get(16), ";");
            buffParam.setProbability(buffParamList.get(0));
            npcAttribute.setThunderBuffParam(buffParam);
        }

        // param -> 击退效果/格子数(与好汉距离1格；与好汉距离2格；与好汉距离3格；与好汉距离4格
        // param2 -> 穿透效果攻击力的千分比(与好汉距离1格；与好汉距离2格；与好汉距离3格；与好汉距离4格
        if (!"0".equals(attributeParamList.get(17))) {
            KowloonBuffParam buffParam = new KowloonBuffParam();
            List<Integer> list = StringUtils.stringToIntegerList(attributeParamList.get(17), ";");
            for (int i = 0; i < list.size(); i++) {
                if (i == 0) {
                    buffParam.setDuration(list.get(i));
                } else if (i == 1) {
                    buffParam.setBuffMaxCount(list.get(i));
                } else {
                    buffParam.getParam().add(list.get(i));
                }
            }
            buffParam.setParam2(StringUtils.stringToIntegerList(attributeParamList.get(18), ";"));
            npcAttribute.setBeatBackParam(buffParam);
        }

        // 加攻效果（好汉最大攻击力的千分比；buff叠加次数上限）
         if (!"0".equals(attributeParamList.get(19))) {
             KowloonBuffParam buffParam = new KowloonBuffParam();
            List<Integer> buffParamList = StringUtils.stringToIntegerList(attributeParamList.get(19), ";");
             buffParam.setProbability(buffParamList.get(0));
             buffParam.setBuffMaxCount(buffParamList.get(1));
             // 加攻范围
             buffParam.getParam().add(Integer.parseInt(attributeParamList.get(20)));
            npcAttribute.setAtkBuffParam(buffParam);
        }
        return npcAttribute;
    }

}
